FOJ 1207 半数集问题

原题:

http://acm.fzu.edu.cn/problem.php?pid=1207

解题分析:

要注意的有三点:

1)  "从 N 开始依次产生半数集 ......". 要注意 " 依次 " 的表述 , 说明半数集中元素的产生是有先后顺序的 . 这对后面的排除重复元素很重要 .

2)  "在 N 的左边加上一个自然数 , 但该自然数不能超过最近添加数的一半 ." 这是构造解集的重要条件 , 引导我们使用递归方法解决此题 ..

3)  "半数集不是多重集 . 集合中已经有的元素不再添加到集合中 ". 配合 1), 就可以了解产生重复的原因 .


重复分析:  假设 N=50. 那么会出现如下情况 :

          50 -> 12 50

          50 -> 2 50 -> 1 2 50  (与之前产生的 1250 重复 , 重复一次 )

其实, 重复造成的问题不止如此 , 考虑下面的情况 :

50 -> 48 50

50 -> 8 50 -> 4 8 50 

4 8 50与已经产生的  48 50 重复 . 这不仅造成自身不能添加到半数集中 , 而且使得由 4 8 50 扩展形成的  2 4 8 50 和 1 2 4 8 50 都不会出现在半数集中 .

 
所以, 扣除重复元素的操作要注意两个问题 :

1)  产生重复的条件.
2)  应该扣除多少个元素.

产生重复的条件:  根据题意 , 0<N<201,  所以 , 0<N/2<=100. 第二次添加的数肯定是个两位数 . 也就是说 , 重复是由于一个两位数和两个一位数的冲突造成的 . 由添加数的规则可得 , 当添加的数为 i 时 , 若  i > 9 && ( (i / 10) <= (1 % 10) / 2).

应该扣除的个数:  由构造的顺序性可知 , 与一个两位数构造成的半数集元素重复的元素不能添加到半数集中 .  要扣除的个数就是由最左边的一位数能够产生的半数集数量 . 例如 ,

    50 -> 48 50

    50 -> 8 50 -> 4 8 50

要扣除的数量就是4 能够产生的半数集元素个数。

源码:(VC++)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值